home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / grafik / viewer / amipeg06 / ham8.c < prev    next >
C/C++ Source or Header  |  1996-07-15  |  10KB  |  404 lines

  1. /*
  2.  *  This source copes with all amiga-specific stuff as opening the screen, resizing
  3.  *  it using user copper lists, etc.
  4.  *
  5.  *  Copper-based resizing is now implemented, although no aspect ratio is taken care of.
  6.  *
  7.  *  HAM6 is supported now.
  8.  *
  9.  *  Michael Rausch  14-4-94  1:11:59
  10.  *
  11.  *  Some fixes to allow for non-default monitors
  12.  *
  13.  *  Miloslaw Smyk  21-2-96
  14.  */
  15.  
  16. #include <proto/exec.h>
  17. #include <proto/intuition.h>
  18. #include <proto/graphics.h>
  19. #include <proto/asl.h>
  20.  
  21. #include <libraries/asl.h>
  22. #include <exec/memory.h>
  23. #include <hardware/custom.h>
  24. #include <graphics/copper.h>
  25. #include <graphics/gfxbase.h>
  26. #include <graphics/gfxmacros.h>
  27. #include <graphics/videocontrol.h>
  28. #include <graphics/displayinfo.h>
  29. #include <graphics/display.h>
  30.  
  31. #include <dos/dos.h>
  32. #include <proto/dos.h>
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37.  
  38. #include "video.h"
  39. #include "proto.h"
  40. extern int ditherType;
  41.  
  42. extern void HAM8_Init(struct RastPort *);    // kinda static
  43. extern void HAM8_Init_lores(struct RastPort *);
  44. extern void HAM6_Init_lores(struct RastPort *);
  45.  
  46. void (*HAM8_draw)(void *, int, int);
  47.  
  48.  
  49. #define custom ((*(volatile struct Custom *)(0xdff000)))
  50.  
  51.  
  52. struct IntuitionBase *IntuitionBase;
  53. /* struct GfxBase *GfxBase; */
  54. extern struct ExecBase *SysBase;
  55. static struct Screen *screen;
  56. static ULONG soerror = NULL;
  57.  
  58. int gfxver;
  59. ULONG *kaiko = NULL;
  60.  
  61. int lores=TRUE, sdbl=TRUE, ham6=FALSE;
  62.  
  63. int max_x, max_y;
  64.  
  65. static struct ColorSpec firstblack[2]={ {0,0,0,0}, {-1, 0,0,0} };    /* Color 0 is 0x000*/
  66.  
  67.  
  68. static void Quit(char *why, int failcode)
  69. {
  70.     puts(why);
  71.     exit(failcode);
  72. }
  73.  
  74. static void output_term(void)
  75. {
  76.     close_timer();
  77.  
  78.     if (screen)
  79.     {
  80.         FreeVPortCopLists(&(screen->ViewPort));
  81.         RemakeDisplay();
  82.         CloseScreen(screen);
  83.     }
  84.     if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
  85.     if (GfxBase) CloseLibrary((struct Library *) GfxBase);
  86. }
  87.  
  88.  
  89. int get_ham_modeid(void)
  90. {
  91.     struct ScreenModeRequester *scrMdReq;
  92.     int modeid = 0xffffffff;
  93.  
  94.     if(scrMdReq = AllocAslRequestTags(ASL_ScreenModeRequest,
  95.                                                                         ASLSM_MinWidth, 200,
  96.                                                                         ASLSM_MinHeight, 200,
  97.                                                                         ASLSM_MinDepth, 6,
  98.                                                                         ASLSM_MaxDepth, 8,
  99.                                                                         ASLSM_PropertyFlags, DIPF_IS_HAM,
  100.                                                                         ASLSM_PropertyMask, DIPF_IS_HAM,
  101.                                                                         TAG_DONE))
  102.     {
  103.         if(AslRequestTags(scrMdReq, TAG_DONE))
  104.             modeid = scrMdReq->sm_DisplayID;
  105.  
  106.         FreeAslRequest(scrMdReq);
  107.     }
  108.  
  109.     return(modeid);
  110. }
  111.  
  112.  
  113. void InitColorDisplay(void)
  114. {
  115.     atexit(output_term);
  116.  
  117.     if ((GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",37))==NULL)
  118.         Quit("graphics.library is too old, <V39",25);
  119.     if ((IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",37))==NULL)
  120.         Quit("intuition.library is too old, <V39",25);
  121.  
  122.     gfxver = GfxBase->LibNode.lib_Version;
  123.     if(gfxver>=40) kaiko = GfxBase->ChunkyToPlanarPtr;
  124.  
  125.     HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  126.     DoDitherImage = NoDitherImage;
  127.  
  128.     if((modeid == 0xffffffff) && ((modeid = get_ham_modeid()) == 0xffffffff))
  129.         Quit("aMiPEG: unable to open HAM display...", 25);
  130. }
  131.  
  132.  
  133. /*
  134.  *   Resize the display using a copper list. Nifty'n neat amiga feature.
  135.  *
  136.  *   Phew ... takes now 2 hours to fiddle the system-compliant custom modulo stuff.
  137.  */
  138. void ResizeDisplay(int w, int h)
  139. {
  140.     struct UCopList *ucoplist;
  141.     static struct TagItem uCopTags[] = {
  142.         { VC_NoColorPaletteLoad, TRUE },
  143.         { VTAG_USERCLIP_SET, NULL },
  144.         { VTAG_END_CM, NULL }};
  145.     int i,j,k, y, fp_each, locallores;
  146.     struct CopList *dspins;
  147.     struct CopIns *copins;
  148.     short bpl1mod=-1, bpl2mod=-1, last1, last2, this1, this2;
  149.     ULONG id;
  150.     struct DimensionInfo dim_info;
  151.     BOOL quit = FALSE;
  152.     struct IntuiMessage *msg;
  153.     static char win_title[256];
  154.  
  155.     if(ditherType == NO_DITHER) return;
  156.  
  157.     if(ditherType == CYBERGFX_DITHER || ditherType == CYBERGFXGRAY_DITHER || ditherType == GRAY_DITHER)
  158.     {
  159.         ModifyIDCMP(cyber_window, IDCMP_NEWSIZE);
  160.  
  161.         SizeWindow(cyber_window, w - 160, h - 120);
  162.  
  163.         sprintf(win_title, "%s [%dx%d]", FilePart(animname), w, h);
  164.         SetWindowTitles(cyber_window, win_title, (UBYTE *)~0);
  165.  
  166.         while(!quit)
  167.         {
  168.             WaitPort(cyber_window->UserPort);
  169.             while(msg = (struct IntuiMessage *)GetMsg(cyber_window->UserPort))
  170.             {
  171.                 if(msg->Class == IDCMP_NEWSIZE)
  172.                     quit = TRUE;
  173.  
  174.                 ReplyMsg((struct Message *)msg);
  175.             }
  176.         }
  177.  
  178.         ModifyIDCMP(cyber_window, CLOSEWINDOW | MOUSEBUTTONS);
  179.  
  180.         original_x = cyber_window->Width;
  181.         original_y = cyber_window->Height;
  182.         return;
  183.     }
  184.  
  185.     id = modeid & MONITOR_ID_MASK;
  186.  
  187.     if (GetDisplayInfoData(FindDisplayInfo(id), (UBYTE *)&dim_info, sizeof(struct DimensionInfo), DTAG_DIMS, 0))
  188.         max_y=dim_info.StdOScan.MaxY - dim_info.StdOScan.MinY + 1;
  189.     else
  190.         max_y=200;
  191.  
  192.     if(h>max_y)
  193.         sdbl=FALSE, max_y<<=1;
  194.  
  195.     if(!(GfxBase->ChipRevBits0 & (GFXF_AA_ALICE|GFXF_AA_LISA)))
  196.         ham6 = TRUE;
  197.  
  198.     if(ham6)
  199.         lores=TRUE;
  200.     locallores = lores && (w<=160);
  201.     max_x = (locallores ? 320 : 640);
  202.  
  203.     switch(id)
  204.     {
  205.         case A2024_MONITOR_ID:
  206.             Quit("Get some colors, dude.", 25);
  207.  
  208.         case DBLPAL_MONITOR_ID: /* ARGH!  Kick their butts for this one! */
  209.             if(sdbl)
  210.                 id = locallores ? DBLPALLORESHAMFF_KEY : DBLPALHIRESHAMFF_KEY;
  211.             else
  212.                 id = locallores ? DBLPALLORESHAM_KEY : DBLPALHIRESHAM_KEY;
  213.             break;
  214.  
  215.         case DBLNTSC_MONITOR_ID:
  216.             if(sdbl)
  217.                 id = locallores ? DBLNTSCLORESHAMFF_KEY : DBLNTSCHIRESHAMFF_KEY;
  218.             else
  219.                 id = locallores ? DBLNTSCLORESHAM_KEY : DBLNTSCHIRESHAM_KEY;
  220.             break;
  221.  
  222.         case EURO72_MONITOR_ID:
  223.             if(sdbl)
  224.                 id = locallores ? EURO72LORESHAMDBL_KEY : EURO72PRODUCTHAMDBL_KEY;
  225.             else
  226.                 id = locallores ? EURO72LORESHAM_KEY : EURO72PRODUCTHAM_KEY;
  227.             break;
  228.  
  229.         case VGA_MONITOR_ID:
  230.             if(sdbl)
  231.                 id = locallores ? VGALORESHAMDBL_KEY : VGAPRODUCTHAMDBL_KEY;
  232.             else
  233.                 id = locallores ? VGALORESHAM_KEY : VGAPRODUCTHAM_KEY;
  234.             break;
  235.  
  236.         case PAL_MONITOR_ID:
  237.         case NTSC_MONITOR_ID:
  238.             if(gfxver >= 40 && sdbl)
  239.                 id = locallores ? id | LORESHAMSDBL_KEY: id | HIRESHAMSDBL_KEY;
  240.             else
  241.                 sdbl=FALSE, id = locallores ? id | HAM_KEY : id | HIRESHAM_KEY;
  242.             break;
  243.  
  244.         default:
  245.             printf("ModeID 0x%x either doesn't support HAM or is unknown to aMiPEG.", id);
  246.             Quit("", 10);
  247.     }
  248.  
  249.     if(!(screen=OpenScreenTags(NULL,
  250.         SA_DisplayID,    id,
  251.         SA_Depth,    ham6?6:8,
  252.         SA_Width,    max_x,
  253.         SA_Colors,    firstblack,
  254.         SA_Type,    CUSTOMSCREEN|SCREENQUIET,
  255.         SA_Quiet,     TRUE,
  256.         SA_Interleaved,    !ham6, //TRUE,
  257.         SA_Overscan,    OSCAN_STANDARD,
  258.         SA_MinimizeISG,    TRUE,
  259.         SA_ErrorCode,    &soerror,
  260.         TAG_END))) Quit("Couldn't open screen.",25);
  261.  
  262.     if((screen->RastPort.BitMap->Depth == 6) && !ham6)
  263.         Quit("Incorrect depth. Please try to specify \"-dither ham6\" explicitely.",25);
  264.  
  265.     if(lores) {
  266.         if(ham6)
  267.         {    // the new ham6 routines do not handle interleaved bitmaps anymore
  268.             HAM6_Init_lores(&(screen->RastPort));
  269.             HAM8_draw = HAM6_draw_lores;
  270.             DoDitherImage = ColorDitherImage_12bit;
  271.         } else {
  272.             HAM8_Init_lores(&(screen->RastPort));
  273.             HAM8_draw = HAM8_draw_lores;
  274.             DoDitherImage = ColorDitherImage_lores;    // lacks kaiko support, actually
  275.         }
  276.         max_x >>=1;
  277.  
  278.     } else {
  279.         HAM8_Init(&(screen->RastPort));
  280.         HAM8_draw = HAM8_draw_hires;
  281.         DoDitherImage = ColorDitherImage;    // kaiko on one day
  282.         max_x >>=2;
  283.     }
  284.  
  285.     if(noDisplayFlag)
  286.         HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  287.  
  288.  
  289.     /* the memory is freed upon exit in output_term via FreeVPortCopLists */
  290.     if(!(ucoplist = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR)))
  291.         Quit("No memory for copper list.",25);
  292.  
  293.     /* fiddle out some hardware values from this screen's init copper list */
  294.     dspins=screen->ViewPort.DspIns;
  295.     copins=dspins->CopIns;
  296.     for(i=dspins->Count-1; i>=0; i--, copins++)
  297.     {
  298.         j = copins->DESTDATA;
  299.  
  300.         switch(copins->DESTADDR & 0xfff)    // argh! kick 2.1 messes this up!
  301.         {        
  302.             case (int)&((*(struct Custom *)(0)).bpl1mod):
  303.                 last1=bpl1mod = j;
  304.                 break;
  305.             case (int)&((*(struct Custom *)(0)).bpl2mod):
  306.                 last2=bpl2mod = j;
  307.                 break;
  308.         }
  309.     }
  310.  
  311.     if(bpl1mod==-1 || bpl2mod==-1)
  312.     {
  313.         printf("ooops\n");
  314.         return;    /* hmmm? */
  315.     }
  316.  
  317.     if((bpl1mod == bpl2mod) && sdbl) sdbl=FALSE;
  318.  
  319.     y = screen->Height;
  320.     (void) CINIT(ucoplist, y*3);        /* ... instructions per line */
  321.  
  322.  
  323.     if(sdbl)
  324.     {
  325.         /*
  326.          *  We abuse some of AGA's features here; double-scanning is implemented
  327.          *  by applying bpl1mod to ALL planes on one line, bpl2mod on the next.
  328.          *  Obviously, double-scanning enables some kind of internal chipmem cache.
  329.          *  At least, it's faster. And (because of?) less copper instructions.
  330.          */
  331.  
  332.         fp_each = ((y*2)<<8) / (short)h;
  333.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  334.         {
  335.  
  336.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  337.                 this1=bpl1mod;
  338.             else                        /* finally, we are ready; next one */
  339.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  340.  
  341.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  342.                 this2=bpl1mod;
  343.             else                        /* finally, we are ready; next one */
  344.                 this2=bpl2mod, k=(k&0xff)+fp_each;
  345.  
  346.             if(last1!=this1 || last2!=this2)
  347.                 CWAIT(ucoplist, j, 0);
  348.  
  349.             if(last1!=this1)
  350.             {
  351.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  352.                 last1=this1;
  353.             }
  354.  
  355.             if(last2!=this2)
  356.             {
  357.                 CMOVE(ucoplist, custom.bpl2mod, this2);
  358.                 last2=this2;
  359.             }
  360.         }
  361.     } else {
  362.         /*
  363.          *  No scan-doubling possible; most probably because of a pal/ntsc screen 
  364.          *  and no V40 graphics library available.
  365.          */
  366.  
  367.         bpl1mod -= screen->RastPort.BitMap->BytesPerRow;
  368.  
  369.         fp_each = (y<<8) / (short)h;
  370.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  371.         {
  372.  
  373.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  374.                 this1=bpl1mod;
  375.             else                        /* finally, we are ready; next one */
  376.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  377.  
  378.             if(last1!=this1)
  379.             {
  380.                 CWAIT(ucoplist, j, 0);
  381.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  382.                 CMOVE(ucoplist, custom.bpl2mod, this1);
  383.                 last1=this1;
  384.             }
  385.         }
  386.     }
  387.  
  388.     /*
  389.      *  Pretty nifty, isn't it? Finally, even a little bit copper-list-optimizing is build in!
  390.      */
  391.  
  392.     CEND(ucoplist);
  393.  
  394.     /* Set the freshly created user copper list */
  395.     //Forbid();
  396.     screen->ViewPort.UCopIns = ucoplist;
  397.     //Permit();
  398.  
  399.     /*  Enable user copper list clipping for this ViewPort.  */
  400.     (void) VideoControl( screen->ViewPort.ColorMap, uCopTags );
  401.  
  402.     RethinkDisplay();
  403. }
  404.